"""
人脸数据仓库
遵循开发规范，提供人脸数据的CRUD操作
"""
from typing import List, Optional
import numpy as np
from database.orm_models import FaceORM
from models.database_models import FaceModel
from repositories.orm_base_repository import ORMBaseRepository
from utils.logger import app_logger


class ORMFaceRepository(ORMBaseRepository[FaceORM]):
    """人脸数据仓库"""

    def __init__(self):
        super().__init__(FaceORM)

    # ==================== 转换方法 ====================

    def _orm_to_model(self, orm: FaceORM) -> Optional[FaceModel]:
        """ORM → Database Model 转换"""
        if not orm:
            return None

        # 特征向量从BLOB转换为numpy数组
        feature_vector = None
        if orm.feature_vector:
            try:
                feature_vector = np.frombuffer(orm.feature_vector, dtype=np.float32)
            except Exception as e:
                app_logger.error(f"特征向量解析失败: {e}")

        return FaceModel(
            id=orm.id,
            face_id=orm.face_id,
            person_id=orm.person_id,
            person_name=orm.person_name,
            feature_vector=feature_vector,
            quality_score=orm.quality_score or 0.0,
            face_rect=orm.face_rect,
            image_path=orm.image_path,
            meta_info=orm.meta_info,
            is_active=orm.is_active,
            created_at=orm.created_at,
            updated_at=orm.updated_at
        )

    def _model_to_orm(self, model: FaceModel) -> FaceORM:
        """Database Model → ORM 转换"""
        # 特征向量从numpy数组转换为bytes
        feature_vector_bytes = None
        if model.feature_vector is not None:
            feature_vector_bytes = model.feature_vector.astype(np.float32).tobytes()

        return FaceORM(
            id=model.id if model.id else None,
            face_id=model.face_id,
            person_id=model.person_id,
            person_name=model.person_name,
            feature_vector=feature_vector_bytes,
            quality_score=model.quality_score,
            face_rect=model.face_rect,
            image_path=model.image_path,
            meta_info=model.meta_info,
            is_active=model.is_active
        )

    # ==================== 业务方法 ====================

    def get_face_by_face_id(self, face_id: str, include_deleted: bool = False) -> Optional[FaceModel]:
        """
        根据face_id获取人脸
        
        Args:
            face_id: 人脸ID
            include_deleted: 是否包含已删除的记录（默认False）
        
        Returns:
            人脸模型，未找到返回None
        """
        try:
            conditions = [FaceORM.face_id == face_id]
            
            # 默认只查询有效记录
            if not include_deleted:
                conditions.append(FaceORM.is_active == True)
            
            orm_results = self.find_models(where_conditions=conditions)
            
            if orm_results:
                return self._orm_to_model(orm_results[0])
            return None

        except Exception as e:
            app_logger.error(f"根据face_id查询失败: {face_id}, 错误: {e}", exc_info=True)
            raise

    def get_faces_by_person_id(self, person_id: str, only_active: bool = True) -> List[FaceModel]:
        """根据person_id获取人脸列表"""
        try:
            conditions = [FaceORM.person_id == person_id]
            if only_active:
                conditions.append(FaceORM.is_active == True)

            orm_results = self.find_models(where_conditions=conditions)
            return [self._orm_to_model(orm) for orm in orm_results]

        except Exception as e:
            app_logger.error(f"根据person_id查询失败: {person_id}, 错误: {e}", exc_info=True)
            raise

    def get_all_active_faces(self) -> List[FaceModel]:
        """获取所有启用的人脸"""
        try:
            orm_results = self.find_models(
                where_conditions=[FaceORM.is_active == True]
            )
            return [self._orm_to_model(orm) for orm in orm_results]

        except Exception as e:
            app_logger.error(f"查询所有启用人脸失败: {e}", exc_info=True)
            raise

    def add_face(self, model: FaceModel) -> str:
        """
        添加人脸

        Args:
            model: 人脸模型

        Returns:
            face_id
        """
        try:
            orm = self._model_to_orm(model)
            self.insert_model(orm)
            app_logger.info(f"人脸添加成功: face_id={model.face_id}")
            return model.face_id

        except Exception as e:
            app_logger.error(f"人脸添加失败: {e}", exc_info=True)
            raise

    def update_face(self, model: FaceModel) -> bool:
        """更新人脸信息"""
        try:
            orm = self._model_to_orm(model)
            return self.update_model(orm)

        except Exception as e:
            app_logger.error(f"人脸更新失败: {e}", exc_info=True)
            raise

    def delete_face_by_face_id(self, face_id: str) -> bool:
        """
        根据face_id删除人脸（逻辑删除）

        Args:
            face_id: 人脸ID

        Returns:
            是否成功
        """
        try:
            face_model = self.get_face_by_face_id(face_id)
            if not face_model:
                app_logger.warning(f"人脸不存在: face_id={face_id}")
                return False

            face_model.is_active = False
            return self.update_face(face_model)

        except Exception as e:
            app_logger.error(f"删除人脸失败: {face_id}, 错误: {e}", exc_info=True)
            raise

    def count_faces(self, only_active: bool = True) -> int:
        """统计人脸数量"""
        try:
            conditions = [FaceORM.is_active == True] if only_active else None
            return self.count_models(where_conditions=conditions)

        except Exception as e:
            app_logger.error(f"统计人脸数量失败: {e}", exc_info=True)
            raise

    def get_all_face_features(self, only_active: bool = True) -> List[tuple]:
        """
        获取所有人脸特征（用于重建索引）

        Returns:
            [(face_id, feature_vector), ...]
        """
        try:
            conditions = [FaceORM.is_active == True] if only_active else None
            orm_results = self.find_models(where_conditions=conditions)

            features = []
            for orm in orm_results:
                if orm.feature_vector:
                    try:
                        vector = np.frombuffer(orm.feature_vector, dtype=np.float32)
                        features.append((orm.face_id, vector))
                    except Exception as e:
                        app_logger.error(f"解析特征向量失败: face_id={orm.face_id}, 错误: {e}")
                        continue

            return features

        except Exception as e:
            app_logger.error(f"获取人脸特征失败: {e}", exc_info=True)
            raise
